﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Infrastructure.DynamicProxy
{
    internal class DynamicProxy<T> : DispatchProxy
    {
        public T? decorated { get; set; }//目标类
        public Action<object?[]?>? _afterAction { get; set; }  // 动作之后执行
        public Action<object?[]?, object>? _beforeAction { get; set; } // 动作之前执行
        protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
        {
            Exception exception = null;
            AfterAction(args);
            object result = null;
            try
            {
                //调用实际目标对象的方法
                result = targetMethod?.Invoke(decorated, args);
            }
            catch (Exception ex)
            {
                exception = ex;
            }
            BeforeAction(args, result);
            //调用完执行方法后的委托，如果有异常，抛出异常
            if (exception != null)
            {
                throw exception;
            }
            return result;
        }

        /// <summary>
        /// 创建代理实例
        /// </summary>
        /// <param name="decorated">代理的接口类型</param>
        /// <param name="afterAction">方法执行前执行的事件</param>
        /// <param name="beforeAction">方法执行后执行的事件</param>
        /// <returns></returns>
        public T Create(T decorated, Action<object?[]?> afterAction, Action<object?[]?, object> beforeAction)
        {
            object proxy = Create<T, DynamicProxy<T>>(); // 调用DispatchProxy 的Create  创建一个新的T
            DynamicProxy<T> proxyDecorator = (DynamicProxy<T>)proxy;
            proxyDecorator.decorated = decorated;
            //把自定义的方法委托给代理类
            proxyDecorator._afterAction = afterAction;
            proxyDecorator._beforeAction = beforeAction;
            return (T)proxy;
        }


        private void AfterAction(object?[]? args)
        {
            try
            {
                _afterAction.Invoke(args);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"执行之前异常：{ex.Message}，{ex.StackTrace}");
            }
        }

        private void BeforeAction(object?[]? args, object? result)
        {
            try
            {
                _beforeAction.Invoke(args, result);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"执行之后异常：{ex.Message}，{ex.StackTrace}");
            }
        }


    }
}
